# !/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
@作者 杨阳
@时间 2018-06-01
@说明 自动生成routes的工具类
@注意事项
"""
import os

from util import DateUtil
from util.generation.generationutil import GenerationConstant
from util.generation.generationutil import GenerationMySqlUtil
from util.generation.generationutil.GenerationConstant import 不生成在查询中的列, 不生成在修改中的列, 不生成在增加中的列
from util.generation.generationutil.GenerationWriteFileUtil import tab, w, change_line, delete_files


def write_encoding_and_annotation(fp, table_name):
    """
    写入model类的文件编码以及注释
    :param  fp          文件对象
    :param  table_name  表名
    :return:
    """
    w(fp, "# !/usr/bin/env python3")
    w(fp, "# -*- coding: utf-8 -*-")
    w(fp, "")
    w(fp, "\"\"\"")
    w(fp, "@作者 杨阳")
    w(fp, "@时间 {}".format(DateUtil.format_date()))
    w(fp, "@说明 {}表对应的routes文件".format(table_name))
    w(fp, "@注意事项")
    w(fp, "\"\"\"")


def write_import_file(fp, model_name):
    """
    生成需要导入的文件
    :param fp:      文件对象
    :return:
    """
    w(fp, "from flask import Blueprint, request")
    w(fp, "from util.JsonUtil import classToDict, JsonEncoder")
    w(fp, "from util.SessionUtil import Mast_be_login_decorator")
    w(fp, "import json")
    w(fp, "from model.{} import {}".format(model_name, model_name))


def write_get_entity_byId(fp, model_name, table_sort_name):
    """
    生成根据id返回实体类的方法
    :param fp:                      文件操作对象
    :param model_name:              表对应实体类名称
    :param table_sort_name:         表名的简写，通知是去掉t_
    :return:
    """
    w(fp, "@{}.route(\"/get/<id>\", methods=[\"GET\"])".format(table_sort_name))
    w(fp, "@Mast_be_login_decorator")
    w(fp, "def get_entity_byId(id):")

    # 生成注释
    w(fp, tab() + "\"\"\"")
    w(fp, tab() + "根据id获得实体")
    w(fp, tab() + ":return: json 字符串")
    w(fp, tab() + "\"\"\"")

    w(fp, tab() + "{}={}.get_entity_byId(id)".format(table_sort_name, model_name))
    w(fp, tab() + "result = {\"success\": True, \"%s\": classToDict(%s)}" % (table_sort_name, table_sort_name))
    w(fp, tab() + "return json.dumps(result, cls=JsonEncoder)")


def write_save_entity(fp, columns, model_name, table_sort_name):
    """
    生成保存实体类的方法
    :param fp:                  文件操作对象
    :param columns:             表中的列
    :param model_name:          表对应的实体类的名称
    :param table_sort_name:     相当于简名的简写
    :return:                    json字符串
    """
    w(fp, "@{}.route(\"/save/\", methods=[\"POST\"])".format(table_sort_name))
    w(fp, "@Mast_be_login_decorator")
    w(fp, "def save_entity():")

    # 注释
    w(fp, tab() + "\"\"\"")
    w(fp, tab() + "保存实体")
    w(fp, tab() + ":return: json 字符串")
    w(fp, tab() + "\"\"\"")

    # 方法体,接收表单参数
    for column in columns:
        column_name = column["COLUMN_NAME"]
        if column_name != "create_time" and column_name != "password" and column_name != "creator":
            w(fp, tab() + "{}=request.form.get(\"{}\")".format(column_name, column_name))

    w(fp, tab() + "if id and id != '':")
    w(fp, tab() + tab() + "return {}.update_entity({})"
      .format(model_name, get_update_entity_grid_params(columns, True)))
    w(fp, tab() + "else:")
    w(fp, tab() + tab() + "return {}.add_entity({})"
      .format(model_name, get_update_entity_grid_params(columns, False)))


def write_entity_grid(fp, columns, model_name, table_sort_name):
    """
    生成查询实体类表格数据的方法
    :param fp:                  文件操作对象
    :param columns:             表中的所有列
    :param model_name:          表对应的实体类
    :param table_sort_name:     表名的简写
    :return:                    json字符串
    """
    w(fp, "@{}.route(\"/grid/\", methods=[\"POST\"])".format(table_sort_name))
    w(fp, "@Mast_be_login_decorator")
    w(fp, "def entity_grid():")

    # 注释
    w(fp, tab() + "\"\"\"")
    w(fp, tab() + "查询实体类表格形式的数据")
    w(fp, tab() + ":return: json 字符串")
    w(fp, tab() + "\"\"\"")

    # 方法体
    w(fp, tab() + "current_page = request.form.get(\"current_page\")")
    w(fp, tab() + "group_id = request.form.get(\"group_id\")")
    for column in columns:
        column_name = column["COLUMN_NAME"]
        data_type = column["DATA_TYPE"]
        if column_name not in 不生成在查询中的列:
            if data_type == 'datetime' or data_type == 'date':
                w(fp, tab() + "search_start_{}=request.form.get(\"search_start_{}\")"
                  .format(column_name, column_name))
                w(fp, tab() + "search_end_{}=request.form.get(\"search_end_{}\")"
                  .format(column_name, column_name))
            else:
                w(fp, tab() + "search_{}=request.form.get(\"search_{}\")".format(column_name, column_name))

    params = get_query_entity_grid_params(columns, False)

    w(fp, tab() + "return {}.query_entity_grid(group_id, {}, current_page)"
      .format(model_name, params))
    pass


def get_update_entity_grid_params(columns, include_id):
    """
    拼接查询实体类表格方法的参数
    :param columns:     表格中所有的列
    :param include_id   是否包含id
    :return:
    """
    list = []
    for column in columns:
        column_name = column["COLUMN_NAME"]
        if include_id:  # 包含id说明是修改
            if column_name not in 不生成在修改中的列:
                list.append(column_name)
        else:
            if column_name not in 不生成在增加中的列:
                list.append(column_name)

    return ",".join(list)


def get_query_entity_grid_params(columns, include_id):
    """
    拼接查询实体类表格方法的参数
    :param columns:     表格中所有的列
    :param include_id   是否包含id
    :return:
    """
    list = []
    for column in columns:
        column_name = column["COLUMN_NAME"]
        data_type = column["DATA_TYPE"]
        if not include_id:
            if column_name not in 不生成在查询中的列:
                if data_type == 'datetime' or data_type == 'date':
                    list.append("search_start_" + column_name)
                    list.append("search_end_" + column_name)
                else:
                    list.append("search_" + column_name)
        else:
            list.append(column_name)

    return ",".join(list)


def write_delete_entity_byId(fp, model_name, table_sort_name):
    """
    生成删除实体的方法
    :param fp:                  文件操作对象
    :param model_name:          表对应实体类的对象名
    :param table_sort_name:     表名的简定，一般是去掉前面的t_
    :return:
    """
    w(fp, "@{}.route(\"/delete/<id>\", methods=[\"DELETE\"])".format(table_sort_name))
    w(fp, "@Mast_be_login_decorator")
    w(fp, "def delete_entity(id):")

    # 注释
    w(fp, tab() + "\"\"\"")
    w(fp, tab() + "根据id删除实体类")
    w(fp, tab() + ":return: json 字符串")
    w(fp, tab() + "\"\"\"")

    w(fp, tab() + "return {}.delete_entity_byId(id)".format(model_name))


def generation_routes():
    """
    生成路径文件的方法
    :return:
    """
    print("=========================================开始生成routes文件=========================================")

    # 1. 找到routes文件的路径，删除旧下面的所有文件
    delete_files(GenerationConstant.routes_file_path)

    # 2. 获取所有表名，每一个表生成一个routes文件
    tables = GenerationMySqlUtil.get_database_tables()
    for table in tables:
        table_name = table["table_name"]
        print("表名:{}".format(table_name))
        model_name = table["model_name"]
        print("实体:{}".format(model_name))
        list = table_name.split("_")
        print("list:{}".format(list))
        if 't' in list:
            list.remove('t')
        print("remote 后 list:{}".format(list))
        print("routes文件名：{}_routes.py".format("_".join(list)))
        routes_file = GenerationConstant.routes_file_path + "_".join(list) + "_routes.py"
        print("routes全路径：{}".format(routes_file))
        fp = open(routes_file, 'w')

        # 写入编码
        write_encoding_and_annotation(fp, table_name)
        change_line(fp)

        # 需要导入的文件
        write_import_file(fp, model_name)
        change_line(fp)

        # 这个应该是表名的简写
        table_sort_name = "_".join(list)

        # 生成蓝图
        w(fp, "{}=Blueprint('{}', __name__, url_prefix='/{}')"
          .format(table_sort_name, table_sort_name, table_sort_name))
        change_line(fp)

        # 查询出表格中所有列
        columns = GenerationMySqlUtil.get_table_columns(table_name)

        # 生成查询表格的方法
        write_entity_grid(fp, columns, model_name, table_sort_name)
        change_line(fp)

        # 生成保存实体的方法
        write_save_entity(fp, columns, model_name, table_sort_name)
        change_line(fp)

        # 生成删除实体的方法
        write_delete_entity_byId(fp, model_name, table_sort_name)
        change_line(fp)

        # 生成通过id获得实体类的方法
        write_get_entity_byId(fp, model_name, table_sort_name)
        change_line(fp)

        fp.close()
    print("=========================================生成routes文件完成=========================================")


if __name__ == '__main__':
    generation_routes()
